
#include <BStream>
#include "member_BXmlNode.h"
#include "member_BXmlDocument.h"

using namespace BWE;

bool XmlFilter::Check(const BString& desc)
{
	int end = desc.find('\"');
	if (desc.find(':', 0, end) < end)
		return true;
	if (desc.find('&', 0, end) < end)
		return true;
	if (desc.find('|', 0, end) < end)
		return true;
	return false;
}

XmlFilter::XmlFilter(const BString& desc)
{
	BString str;
	int pos = 0;
	while (pos <= desc.size())
	{
		char ch = desc[pos];
		if (ch == '\"')
		{
			while (desc[++pos] != '\"')
				str.append(desc[pos]);
			pos++;
			continue;
		}
		if (ch == ' ' || ch == ':' || ch == '&' || ch == '|' || ch == 0)
		{
			if (str.size())
			{
				addInfo(str);
				str.reset();
			}
		}
		str.append(ch);
		pos++;
	}
}

void XmlFilter::addInfo(const BString& text)
{
	if (text.beginWith(':') || text.beginWith(' '))
	{
		BString name;
		BString value;
		int equal_end = text.find('=');
		text.substr(name, 1, equal_end);
		text.substr(value, equal_end + 1);
		value.trimmed();
		attribMap[name] = value;
		return;
	}
	if (text.beginWith('&'))
	{
		includeTexts.append(text.cstr() + 1);
		return;
	}
	if (text.beginWith('|'))
	{
		excludeTexts.append(text.cstr() + 1);
		return;
	}
	name = text;
}

bool XmlFilter::operator()(BXmlNode* node) const
{
	if (name.size() && node->name() != name)
		return false;

	for (auto it = attribMap.begin(); it.valid(); ++it)
	{
		if (it.value().empty())
		{
			if (!node->containAttrib(it.key()))
				return false;
		}
		else
		{
			const BString& value = node->attrib(it.key());
			if (it.value() != value)
				return false;
		}

	}

	const BString& text = node->text();
	for (int i = 0; i < includeTexts.size(); i++)
	{
		const BString& itext = includeTexts[i];
		if (!text.contain(itext))
			return false;
	}

	for (int i = 0; i < excludeTexts.size(); i++)
	{
		const BString& etext = excludeTexts[i];
		if (text.contain(etext))
			return false;
	}

	return true;
}

member_BXmlNode::member_BXmlNode(BXmlNode* xmlNode)
{
	boss = xmlNode;
	parent = 0;
	document = 0;
	textDirty = false;
}
member_BXmlNode::~member_BXmlNode()
{

}

BXmlNode* member_BXmlNode::find(XmlFilter& filter)
{
	if (filter(boss))
		return boss;
	for (int i = 0; i < children.size(); i++)
	{
		BXmlNode* child = children[i];
		BXmlNode* ret = xml_member(child)->find(filter);
		if (ret)
			return ret;
	}
	return 0;
}

void member_BXmlNode::collect(XmlFilter& filter, BArray<BXmlNode*>& result)
{
	if (filter(boss))
		result.append(boss);
	for (int i = 0; i < children.size(); i++)
	{
		BXmlNode* child = children[i];
		xml_member(child)->collect(filter, result);
	}
}
void member_BXmlNode::collect(const BString& name, BArray<BXmlNode*>& result)
{
	if (boss->name() == name)
		result.append(boss);
	for (int i = 0; i < children.size(); i++)
	{
		BXmlNode* child = children[i];
		xml_member(child)->collect(name, result);
	}
}
